package com.netease.ticket;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;

import com.netease.ocr.VerifyCodeUtil;
/**
 * 
 * @author bjyangfan
 *提交订单
 */
public class ConfirmSubmit {
	
	private String org_apache_struts_taglib_html_TOKEN;
	private String leftTicketStr;
	private String textfield = "中文或拼音首字母"; //这个应该是固定的
	//private String checkbox0 = "0";
	private String train_no;
	private String ticket_type_order_num;
	private String bed_level_order_num;
	private String start_time;
	private String end_time;
	private String station_train_code;
	private String train_date;
	private String seat_type_code;
	private String from_station_telecode;
	private String to_station_telecode;
	private String from_station_name;
	private String to_station_name;
	
	private String cancel_flag = "1";
	private String id_mode = "Y";
	private String[] passengerTickets = new String[5];
	private String oldPassengers = "";
	private String[] passenger__seat = new String[5];
	private String[] passenger__ticket = new String[5];
	private String[] passenger__name = new String[5];
	private String[] passenger__cardtype = new String[5];
	private String[] passenger__cardno = new String[5];
	private String[] passenger__mobileno = new String[5];
	
	private String checkbox9 = "Y";
	private String randCode;    //验证码
	private String reserve_flag = "A"; //保留的，估计恒为A
	private String tFlag = "dc";  //不知道该值的含义，但没有发现有其他值的情况
	
	private String submitUrl = "http://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=checkOrderInfo&rand=";
	private String confirmInitUrl = "http://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init";
	
	private String queueUrl = "http://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getQueueCount";
	
	private String confirmUrl = "http://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=confirmSingleForQueue";
	private String getPassengerUrl = "http://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getpassengerJson";
	private String waitTimeUrl = "http://dynamic.12306.cn/otsweb/order/myOrderAction.do?method=queryOrderWaitTime&tourFlag=dc";
	public String cookie = null;
	public HttpClient client = null;
	
	private String yzmFileName = "passCodeAction.tiff";
	
	private int passengerNum = 0;
	public String user;
	
	/**
	 * 预定以后获取令牌，需要预先设置cookie
	 * @throws Exception
	 */
	public boolean getToken()throws Exception
	{
		 if(this.client == null) client = new HttpClient();
		 
		 String getTokenUrl = confirmInitUrl;
		 HttpMethod method = new GetMethod(getTokenUrl);
		 
		 Util.setReqHeader(method, "http://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init", this.cookie);
		 
		 String token_prefix = "<input type=\"hidden\" name=\"org.apache.struts.taglib.html.TOKEN\"";
		 String leftTicketStr_prefix = "<input type=\"hidden\" name=\"leftTicketStr\" id=\"left_ticket\"";
		 
		 int startIndex = 0;
		 
		 client.executeMethod(method);
		 
		 String html = method.getResponseBodyAsString();
		 
		 //打印返回的信息
		 //System.out.println(html);
		 
		 startIndex = html.indexOf(token_prefix) + token_prefix.length();
		 
		 
		 org_apache_struts_taglib_html_TOKEN = Util.paseToken(html, startIndex);
	 
		 startIndex = html.indexOf(leftTicketStr_prefix) + leftTicketStr_prefix.length();
 
		 leftTicketStr = Util.paseToken(html, startIndex);
		 
		 System.out.println("拿到令牌：" +  org_apache_struts_taglib_html_TOKEN + " " + leftTicketStr);
		 
		 if(org_apache_struts_taglib_html_TOKEN.length() < 10 || leftTicketStr.length() < 10) return false;
		 
		 return true;
	}
	
	/**
	 * 获取用户购票历史身份信息
	 * @return json
	 * @throws Exception
	 */
	public String getPassenger() throws Exception
	{
		HttpMethod method = new PostMethod(getPassengerUrl);
		Util.setReqHeader(method, confirmInitUrl, cookie);
		client.executeMethod(method);
		return method.getResponseBodyAsString();
	}
	
	/**
	 * 获取验证码
	 * @return
	 */
	public String getRand() throws Exception
	{
		String yzm;
		//Scanner sc =new Scanner(System.in);
		if(this.client == null) client = new HttpClient();
		
		//String getRandUrl = "http://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp";
		//2013-9-11号以后使用下边的地址
		String getRandUrl = "http://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=passenger&rand=randp";
		HttpMethod method = new GetMethod(getRandUrl);
		Util.setReqHeader(method, confirmInitUrl, this.cookie);

		 while(true){
			 try{
				 client.executeMethod(method);
				 
		         //打印服务器返回的状态
			     File storeFile = new File(user + yzmFileName);
			     FileOutputStream output = new FileOutputStream(storeFile);
			     
			     //得到网络资源的字节数组,并写入文件 
			     output.write(method.getResponseBody());
			     output.close();
			     
			     
	//		     System.out.println("请手动输入验证码：");
	//		     yzm = sc.next();
	//		     break;
			     
			  	 yzm = VerifyCodeUtil.crackVerifyCode(user + yzmFileName);
			     yzm = Util.paseYzm(yzm);
			 }catch(Exception ex) {
				 System.out.println(ex.getMessage());
				 continue;
			}
		     
		     System.out.println(",处理后的验证码：" + yzm);
		     if(yzm.length() != 4)continue;
		     else break;
		 }
	     this.randCode = yzm;
	     return yzm;
	}
	
	/**
	 * 获取排队的情况
	 * @return
	 */
	public HashMap<String, String> getQueueCount() throws Exception
	{
		GetMethod method = new GetMethod(queueUrl);
		
		NameValuePair[] param = { 
				new NameValuePair("method", "getQueueCount"),
				new NameValuePair("train_date",train_date),
	            new NameValuePair("train_no",train_no),
	            new NameValuePair("station",station_train_code),
	            new NameValuePair("seat",passenger__seat[0]),
	            new NameValuePair("from",from_station_telecode),
	            new NameValuePair("to",to_station_telecode),
	            new NameValuePair("ticket",leftTicketStr)
		};
		method.setQueryString(param);
		Util.setReqHeader(method, confirmInitUrl, cookie);
		client.executeMethod(method);
		String json = method.getResponseBodyAsString();
		
		System.out.println(json);
		HashMap<String, String> msg = Util.paseSimpleJSON(json);
		if(msg.get("op_2").equals("true"))
		{
			System.out.println("排队人数大于余票张数！");
		}
//		else if(msg.get("op_1").equals("true"))
//		{
//			System.out.println("需要排队！");
//		}
		return msg;
	} 
	
	private String getWaitTime() throws Exception
	{
		GetMethod method = new GetMethod(waitTimeUrl);
		Util.setReqHeader(method, confirmInitUrl, cookie);
		client.executeMethod(method);
		
		HashMap<String,String> ret = Util.paseSimpleJSON(method.getResponseBodyAsString());
		return ret.get("waitTime");
	}
	
	/**
	 * 提交订单
	 * @throws Exception
	 */
	public boolean submit()throws Exception
	{
		if(this.getToken() == false)
		{
			System.out.println("未拿到正确的令牌。");
			return false;
		}
		
		int code = 0;
		HttpMethod method;
		String result = "";
		int maxTryTimes = 60; //最大尝试次数
		Scanner sc = new Scanner(System.in);
		
		//获取用户的身份信息
		//getPassenger();
		
		for(int i= 0;i< maxTryTimes;i++){
			
			if(i >= 9 * maxTryTimes/10)
			{
				System.out.print("验证码不正确，请手动输入：");
				getRand();
				this.submitUrl += sc.next();
			}
			else{
				this.submitUrl += getRand();
			}
			if(this.client == null) client = new HttpClient();
			
			method = getMethod("submit");
			Util.setReqHeader(method, confirmInitUrl, this.cookie);
			
			//AJAX异步请求
			method.setRequestHeader("X-Requested-With","XMLHttpRequest");
			code = client.executeMethod(method);
			result = method.getResponseBodyAsString();
			System.out.println(result);
			
			HashMap<String,String> map = Util.paseSimpleJSON(result);
			String errMsg = map.get("errMsg");
			if(code != 200 || (!errMsg.equals("Y") && !errMsg.contains("售完")))
			{
				System.out.println("提交订单结果:" + method.getStatusLine() + ", 提交失败,刷新验证码继续提交");
				
				this.submitUrl= this.submitUrl.substring(0, this.submitUrl.length()-4);
				continue;
			}
			else 
			{
				break;
			}
			
		}
		
		
		HashMap<String, String> queueInfo = getQueueCount();
		
		//余票张数小于排队人数，退出。其实貌似可以强行提交。
//		if(queueInfo.get("op_2").equals("true"))
//		{
//			//return false;
//			System.out.println("余票张数小于排队人数!");
//		}
			
		//这个必须要有停顿,否则会返回网络错误
		Thread.sleep(1000);
		
		//确认订单
		method = getMethod("confirm");
		
		Util.setReqHeader(method, confirmInitUrl, this.cookie);
		
		code = client.executeMethod(method);
		result = method.getResponseBodyAsString();
		queueInfo = Util.paseSimpleJSON(result);
		if(code != 200)
		{
			System.out.println("确认订单结果:" + method.getStatusLine() + ", 提交失败：");
			System.out.println(method.getResponseBodyAsString());
			return false;
		}
		else if(queueInfo.get("errMsg").contains("Y") || queueInfo.get("errMsg").contains("排队"))
		{
			
			if(queueInfo.get("errMsg").contains("排队"))
			{
				System.out.println("获取排队时间：" + getWaitTime() + "分钟");
				while(!getWaitTime().equals("-1"))
				{
					Thread.sleep(1000);
				}
				
				//排队后继续确认
				client.executeMethod(method);
				result = method.getResponseBodyAsString();
				if(result.indexOf("errMsg\":\"Y\"}") > 0)
				{
					System.out.println("排队占座成功！");
					return true;
				}
				else
				{
					System.out.println("占座失败！");
					return false;
				}
				
			}
			else
			{
				System.out.println("确认订单成功!");
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * 从查询结果中拷贝部分信息
	 */
	public void copyFromTrainInfo(TrainInfo ti)
	{
		if(ti == null)
		{
			System.out.println("null TrainInfo!");
			return;
		}
		station_train_code = ti.station_train_code;
		train_no = ti.trainno4;
		train_date = ti.train_date;
		from_station_telecode = ti.from_station_telecode;
		to_station_telecode = ti.to_station_telecode;
		start_time = ti.train_start_time;
		end_time = ti.arrive_time;
		from_station_name = ti.from_station_name;
		to_station_name = ti.to_station_name;
	}
	
	/**
	 * 添加乘客信息,只有一个乘客的情况
	 * @param passenger_name 第一位乘车人的姓名
	 * @param passenger_cardtype 证件类型（1代表身份证）
	 * @param passenger_cardno 证件号码
	 * @param passenger_mobileno手机号码
	 * @param passenger_seat席别（1硬座， 3硬卧， 4软卧， M一等座，O二等座，P特等座， 9商务舱）
	 * @param passenger_ticket 1成人票，2儿童票，3学生票，4残军票
	 */
	public void fillPassengerInfo(String passenger_name, String passenger_cardtype, String passenger_cardno, 
						String passenger_mobileno, String passenger_seat, String passenger_ticket)
	{
		passenger__name[0] = passenger_name;
		passenger__cardtype[0] = passenger_cardtype;
		passenger__cardno[0] = passenger_cardno;
		passenger__mobileno[0] = passenger_mobileno;
		passenger__seat[0] = passenger_seat;
		passenger__ticket[0] = passenger_ticket;
		bed_level_order_num = "000000000000000000000000000000";
		passengerTickets[0]=passenger_seat + ",0,1,"+ passenger_name + "," + passenger_cardtype + "," + passenger_cardno +"," + passenger_mobileno +",Y";
		passengerNum = 1;
		//oldPassengers = passenger_1_name + ","+ passenger_1_cardtype +"," + passenger_1_cardno;
	}
	
	/** TODO
	 * 添加N个乘客信息
	 */
	public void fillMultiPassengerInfo(ArrayList<PassengerInfo> list)
	{
		passengerNum = list.size();
		if(passengerNum > 5)passengerNum = 5;
		int i = 0;
		
		for(PassengerInfo pi: list)
		{
			if(i > 4)break;//12306目前最多允许5个乘客同时买票
			passenger__seat[i] = pi.seat;
			passenger__ticket[i] = pi.ticket;
			passenger__name[i] = pi.name;
			passenger__cardtype[i] = pi.cardtype;
			passenger__cardno[i] = pi.cardno;
			passenger__mobileno[i] = pi.mobileno;
			passengerTickets[i]=passenger__seat[i] + ",0,1,"+ passenger__name[i] + "," + passenger__cardtype[i] + "," + passenger__cardno[i] +"," + passenger__mobileno[i] +",Y";
			i++;
		}
		
	}
	
	public HttpMethod getMethod(String step)
	{	
		PostMethod method;
		
		NameValuePair[] param_common = { 
			new NameValuePair("org.apache.struts.taglib.html.TOKEN",org_apache_struts_taglib_html_TOKEN),  
            new NameValuePair("leftTicketStr",leftTicketStr),
            new NameValuePair("textfield",textfield),
            //new NameValuePair("checkbox0",checkbox0),
            new NameValuePair("orderRequest.train_date",train_date),
            new NameValuePair("orderRequest.train_no",train_no),  
            new NameValuePair("orderRequest.station_train_code",station_train_code),
            new NameValuePair("orderRequest.from_station_telecode", from_station_telecode),
            new NameValuePair("orderRequest.to_station_telecode",to_station_telecode),  
            new NameValuePair("orderRequest.seat_type_code",seat_type_code),
			new NameValuePair("orderRequest.ticket_type_order_num",ticket_type_order_num),  
	        new NameValuePair("orderRequest.bed_level_order_num",bed_level_order_num),  
	        new NameValuePair("orderRequest.start_time",start_time),  
	        new NameValuePair("orderRequest.end_time",end_time),
	        new NameValuePair("orderRequest.from_station_name",from_station_name),
	        new NameValuePair("orderRequest.to_station_name",to_station_name),
	        new NameValuePair("orderRequest.cancel_flag",cancel_flag),  
	        new NameValuePair("orderRequest.id_mode",id_mode),
//			new NameValuePair("passengerTickets",passengerTickets),  
//	        new NameValuePair("oldPassengers",oldPassengers)
//			new NameValuePair("passenger_1_seat",passenger_1_seat),  
//	        new NameValuePair("passenger_1_ticket",passenger_1_ticket),  
//	        new NameValuePair("passenger_1_name",passenger_1_name),  
//	        new NameValuePair("passenger_1_cardtype", passenger_1_cardtype),
//	        new NameValuePair("passenger_1_cardno",passenger_1_cardno),  
//	        new NameValuePair("passenger_1_mobileno",passenger_1_mobileno),
			
	   	} ;
		
		NameValuePair[] passenger_param = new NameValuePair[passengerNum * 8];
		
		for(int i = 0; i< passengerNum; i++)
		{
			passenger_param[i*8] = new NameValuePair("passengerTickets",passengerTickets[i]);
			passenger_param[i*8+1] = new NameValuePair("oldPassengers", oldPassengers);
			passenger_param[i*8+2] = new NameValuePair("passenger_" + (i+1) + "_seat", passenger__seat[i]);
			passenger_param[i*8+3] = new NameValuePair("passenger_" + (i+1) + "_ticket", passenger__ticket[i]);
			passenger_param[i*8+4] = new NameValuePair("passenger_" + (i+1) + "_name", passenger__name[i]);
			passenger_param[i*8+5] = new NameValuePair("passenger_" + (i+1) + "_cardtype", passenger__cardtype[i]);
			passenger_param[i*8+6] = new NameValuePair("passenger_" + (i+1) + "_cardno", passenger__cardno[i]);
			passenger_param[i*8+7] = new NameValuePair("passenger_" + (i+1) + "_mobileno", passenger__mobileno[i]);
		}
		
		NameValuePair param_unchange[] = 
		{
				new NameValuePair("randCode",randCode),
				new NameValuePair("orderRequest.reserve_flag", reserve_flag)
		};
		
		
		//确认这步比提交少一个tFlag参数
		if(step == "confirm")
		{	
			NameValuePair[] param = new NameValuePair[param_common.length + passenger_param.length + param_unchange.length];
			method = new PostMethod(this.confirmUrl);
			for(int i = 0; i< param_common.length; i++)
			{
				param[i] = param_common[i];
			}
			for(int i = 0; i< passenger_param.length; i++)
			{
				param[param_common.length + i] = passenger_param[i];
			}
			
			for(int i = 0; i< param_unchange.length; i++)
			{
				param[param_common.length + passenger_param.length + i] = param_unchange[i];
			}
			
			method.setRequestBody(param);
			
		}
		else
		{
			method = new PostMethod(this.submitUrl);
			NameValuePair[] param = new NameValuePair[param_common.length + passenger_param.length + param_unchange.length +1];
			for(int i = 0; i< param_common.length; i++)
			{
				param[i] = param_common[i];
			}
			for(int i = 0; i< passenger_param.length; i++)
			{
				param[param_common.length + i] = passenger_param[i];
			}
			
			for(int i = 0; i< param_unchange.length; i++)
			{
				param[param_common.length + passenger_param.length + i] = param_unchange[i];
			}
			
			param[param.length-1] = new NameValuePair("tFlag", tFlag);
			
			method.setRequestBody(param);
		}
		
		method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
		
		return method;
	}

}

